<template>
  <div class="VueFileEditor" :class="mode">
    <div class="code-tool-bar top">
      <span class="file-path">
        <span v-for="(directory, i) in parentDirectorys" :key="i">
          <span>{{directory.name}}</span>
          <span>
            <font-awesome-icon
              class="path-split-icon"
              :icon="['fas', 'chevron-right']"
            />
          </span>
        </span>
        <span>
          <span>{{file.name}}</span>
        </span>
      </span>
      <!-- <span>
        <span v-for="ancestor in selectedAncestors.reverse()" :key="'ancestor-' + ancestor.id">
          <span>{{ancestor.name}}</span>
          <span>/</span>
        </span>
        <span v-for="selectedWidgetConfig in selectedWidgetConfigs" :key="selectedWidgetConfig.id">
          <span>{{selectedWidgetConfig.name}}</span>
          <span>,</span>
        </span>
      </span> -->
      <span class="mode-btn-group">
        <span class="mode-btn" :class="{ active: mode === 'design' }" @click="mode='design'">设计</span>
        <span class="mode-btn" :class="{ active: mode === 'code' }" @click="mode='code'">代码</span>
        <span class="mode-btn" :class="{ active: mode === 'design-code' }" @click="mode='design-code'">拆分</span>
      </span>
    </div>
    <AxisSpace
      class="axis-space"
      ref="axisSpace"
      :handleDragover="handleDragover"
      :handleDrop="handleDrop"
      @click.native="clearSelected"
      @contextmenu.native.prevent="handleControllerContextmenuFn"
    >
      <PagePreviewer v-if="pageConfig" :pageConfig="pageConfig"></PagePreviewer>
      <template v-slot:unscale>
        <WidgetController
          v-for="(widgetConfig, index) in widgetConfigs"
          :key="widgetConfig.id || index"
          :widgetConfig="widgetConfig"
          :isSelectedWidgetConfigIdFn="isSelectedFn"
          :selectWidgetConfigFn="selectWidgetConfigFn"
          :handleControllerContextmenuFn="handleControllerContextmenuFn"
          @click.native.stop
        ></WidgetController>
      </template>
    </AxisSpace>
    <CodeEditor
      class="code-editor"
      ref="codeEditor"
      v-model="content"
      @input="handleCodeInput"
    ></CodeEditor>
  </div>
</template>
<script lang="ts">
import { Component, Inject, Prop, Ref, Vue } from 'vue-property-decorator'
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
import TabInfo from '@/components/application-editor/object-editor-tabs/TabInfo';
import FileEditableObject from '@/core/editable-object/file/FileEditableObject';
import CodeEditor from '@/components/common/code-editor/CodeEditor.vue'
import AxisSpace from '@/components/application-editor/axis-space/AxisSpace.vue'
import PagePreviewer from '@/components/application-editor/previewer/PagePreviewer.vue'
import ApplicationEditor from '@/components/application-editor/ApplicationEditor.vue';
import WidgetController from '@/components/application-editor/axis-space/WidgetController.vue'
import WidgetConfig from '@/core/model/WidgetConfig';
import * as clipboard from 'clipboard-polyfill/text'
import { Select, Option, Button, ButtonGroup, MessageBox } from 'element-ui'

@Component({
  components: {
    AxisSpace,
    CodeEditor,
    PagePreviewer,
    WidgetController,
    FontAwesomeIcon,
    [Select.name]: Select,
    [Option.name]: Option,
    [Button.name]: Button,
    [ButtonGroup.name]: ButtonGroup
  }
})
export default class VueFileEditor extends Vue {
  @Inject('app-editor')
  public appEditor!: ApplicationEditor

  @Prop({ required: true })
  private tabInfo!: TabInfo;

  @Prop({ default: false })
  private active!: boolean;

  @Ref()
  private codeEditor!: CodeEditor

  @Ref()
  private axisSpace!: AxisSpace

  private mode = 'design-code' // design code design-code

  private get fileEditableObject() {
    return this.tabInfo.object as FileEditableObject
  }

  private get parentPath() {
    return this.fileEditableObject.parentPath
  }

  private get parentDirectorys() {
    const parentDirectorys = [...this.fileEditableObject.parentDirectorys]
    parentDirectorys.shift()
    return parentDirectorys
  }

  public get file() {
    return this.fileEditableObject.file
  }

  public get content() {
    return this.file.content
  }

  public set content(content: string) {
    this.file.content = content
  }

  private get fileHandler() {
    return this.fileEditableObject.fileHandler
  }

  private get pageConfig() {
    return this.fileHandler.pageConfig
  }

  private get widgetConfigs() {
    return this.pageConfig?.widgetConfigs || []
  }

  private get selectedWidgetConfigs() {
    return this.fileHandler.selectedWidgetConfigs
  }

  private get selectedAncestors() {
    return this.fileHandler.selectedAncestors
  }

  public get tabInfoKey() {
    const tabInfo = this.tabInfo
    return `${tabInfo.editor.name}:${tabInfo.object.id}`
  }

  private selectWidgetConfigFn (widgetConfig: WidgetConfig, multiSelect: boolean) {
    this.codeEditor.focusCode(widgetConfig._code)
    this.fileHandler.selectWidgetConfig(widgetConfig.id, multiSelect)
  }

  private isSelectedFn(widgetConfig: WidgetConfig) {
    return this.fileHandler.isSelectedWidgetConfigId(widgetConfig.id)
  }

  private async handleControllerContextmenuFn( event: MouseEvent) {
    const clipboardText = await clipboard.readText()
    const meunItems = [
      {
        name: '剪切',
        disable: !this.fileHandler.hasSelected,
        handler: () => {
          this.fileHandler.copySelectedWidgetConfig()
          this.fileHandler.deleteAllSelectedWidgetConfig()
        }
      }, {
        name: '复制',
        disable: !this.fileHandler.hasSelected,
        handler: () => {
          this.fileHandler.copySelectedWidgetConfig()
        }
      }, {
        name: '粘贴',
        disable: !clipboardText,
        handler:(event: MouseEvent) => {
          const {x, y} = this.axisSpace.getAxisPosition(event)
          this.fileHandler.pasteWidgetConfig(Math.round(x), Math.round(y))
        }
      }, {
        name: '删除',
        disable: !this.fileHandler.hasSelected,
        handler: async () => {
          try {
            await MessageBox.confirm('是否删除选中的组件？', '提示', {
              confirmButtonText: '确定',
              cancelButtonText: '取消',
              type: 'warning'
            })
            this.fileHandler.deleteAllSelectedWidgetConfig()
          } catch (error) {/*  */}
        }
      }, {
        name: 'split-line', disable: true
      }, {
        name: '锁定', disable: true
      }, {
        name: '隐藏', disable: true
      }, {
        name: '编组',
        disable: !this.fileHandler.hasSelected,
        handler: () => this.fileHandler.groupSelectedWidgetConfigs()
      }, {
        name: '取消编组',
        disable: !(this.fileHandler.singleSelectedWidgetConfig?._widgetTag === 'WidgetGroup'),
        handler: () => this.fileHandler.ungroupSelectedWidgetConfigs()
      }, {
        name: 'split-line'
      }, {
        name: '置为顶层',
        disable: true
      }, {
        name: '上移一层',
        disable: true
      }, {
        name: '下移一层',
        disable: true
      }, {
        name: '置为底层',
        disable: true
      }
    ]

    this.appEditor.openContextmenu(event, meunItems)
  }

  private handleCodeInput () {
    this.fileHandler.updatePageConfig()
  }

  private handleDragover(event: DragEvent) {
    if (event.dataTransfer && event.dataTransfer.types.indexOf('widgetDefinitionTag'.toLowerCase()) !== -1) {
      event.preventDefault()
    }
  }

  private handleDrop (event: DragEvent, x: number, y: number) {
    if (event.dataTransfer) {
      const widgetDefinitionTag = event.dataTransfer.getData('widgetDefinitionTag'.toLowerCase())
      const widgetDefinition = this.appEditor.getWidgetDefinitionBytag(widgetDefinitionTag)

      if (widgetDefinition) {
        this.fileHandler.addWidget(widgetDefinition, x, y)
      }
    }
  }

  private clearSelected() {
    this.fileHandler.clearSelected()
  }

  private async handleKeydown (event: KeyboardEvent) {
    if (!this.active) {
      return
    }
    console.log(event)
  }

  private async handleKeyup (event: KeyboardEvent) {
    if (!this.active) {
      return
    }
    console.log(event)
  }

  private mounted () {
    document.addEventListener('keydown', this.handleKeydown)
    document.addEventListener('keyup', this.handleKeyup)
    this.$emit('mounted')
  }

  private beforeDestroy () {
    document.removeEventListener('keydown', this.handleKeydown)
    document.removeEventListener('keyup', this.handleKeyup)
  }
}
</script>
<style scoped lang="scss">
@import '~@/style/variables.scss';
.VueFileEditor {
  font-size: 12px;
  height: 100%;

  .mode-btn-group {
    display: block;
    float: right;
  }

  .file-path {
    font-size: 12px;
    padding-left: 10px;
    opacity: 0.5;
  }

  .path-split-icon {
    width: 7px;
    margin: 0 5px;
    vertical-align: middle;
  }

  .mode-btn {
    margin-right: 15px;
    cursor: pointer;
  }

  .mode-btn.active {
    color: $primary-color;
  }

  .code-tool-bar {
    height: 24px;
    line-height: 23px;
    background: $panel-background-color;
    border-bottom: solid 1px $border-color;
    // box-shadow: 0px 5px 10px -5px #000;
    position: relative;
    z-index: 1000;
  }

  .code-editor,
  .axis-space {
    border-top: solid 1px rgba($border-color, 0.5);
  }

  &.design-code {
    .axis-space,
    .code-editor {
      height: calc(50% - 16px);
    }
  }

  &.design {
    .axis-space {
      height: calc(100% - 32px);
    }
    .code-editor  {
      display: none;
    }
  }

  &.code {
    .axis-space {
      display: none;
    }
    .code-editor {
      height: calc(100% - 32px);
    }
  }

  ::v-deep .CodeMirror,
  ::v-deep .CodeMirror-gutters {
    background: $panel-background-color;
  }
}
</style>
